#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,a,b) for(register int i = (a);i <= (b);++i)
#define per(i,a,b) for(register int i = (a);i >= (b);--i) 
#define mkp std::make_pair
typedef long long ll;
typedef unsigned long long ull;
using std::string;using std::cin;using std::cout;
inline bool cmp(int x,int y){return x < y;}

const int N = 1e5+9;
const int inf = 1e9+9;
const double eps = 1e-7;
int _,n,m,a[2*N],opt,u,v,w;
//----------------------------
int head[2*N],ver[2*N],next[2*N],tot;
inline void link(int x,int y){ver[++tot] = y , next[tot] = head[x] , head[x] = tot;}
//----------------------------
int fa[2*N],top[2*N],deep[2*N],size[2*N],son[2*N],id[2*N],b[2*N];

inline void dfs1(int now,int father){
    fa[now] = father , deep[now] = deep[father] + 1 , size[now] = 1;
    for(int i = head[now];i;i = next[i]){
        if(ver[i] == father) continue;
        dfs1(ver[i],now);
        size[now] += size[ ver[i] ];
        son[now] = size[ son[now] ] > size[ ver[i] ] ? son[now] : ver[i];
    }
}

inline void dfs2(int now,int toper){
    top[now] = toper , id[now] = ++id[0] , b[ id[0] ] = a[now];
    if(!son[now]) return;
    dfs2(son[now],toper);
    for(int i = head[now];i;i = next[i]){
        if(id[ ver[i] ]) continue;
        dfs2(ver[i],ver[i]);
    }
}
//----------------------------
int TOT;
struct node{
    int l,r;
    ll tag,sum;
    node * ls , * rs;
    ll dis(){return r-l+1;}
}Tree[4*N];

inline node * create(){return &Tree[++TOT];}

inline void pushup(node * cur){cur->sum = cur->ls->sum + cur->rs->sum;}

inline void pushdown(node * cur){
    cur->ls->tag += cur->tag , cur->rs->tag += cur->tag;
    cur->ls->sum += cur->tag * cur->ls->dis();
    cur->rs->sum += cur->tag * cur->rs->dis();
    cur->tag = 0;
    return;
}

inline void build(node * cur,int l,int r){
    cur->l = l , cur->r = r , cur->tag = 0;
    if(l == r){cur->sum = b[l];return;}
    int mid = (l+r) >> 1;
    cur->ls = create() , cur->rs = create();
    build(cur->ls,l,mid) , build(cur->rs,mid+1,r);
    pushup(cur);
}

inline void edit(node * cur){
    if(v < cur->l || cur->r < u) return;
    if(u <= cur->l && cur->r <= v){
        cur->tag += w , cur->sum += w * cur->dis();
        return;
    }
    if(cur->l == cur->r) return;
    pushdown(cur);
    if(u <= cur->ls->r) edit(cur->ls);
    if(cur->rs->l <= v) edit(cur->rs);
    pushup(cur);
}

inline ll query(node * cur){
    if(v < cur->l || cur->r < u) return 0;
    if(u <= cur->l && cur->r <= v) return cur->sum;
    pushdown(cur);
    return query(cur->ls) + query(cur->rs);
}

//----------------------------
int main(){
    std::ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin >> n >> m;
    rep(i,1,n) cin >> a[i];
    rep(i,1,n-1){
        cin >> u >> v;
        link(u,v) , link(v,u);
    }
    dfs1(1,1) , dfs2(1,1);
    node * root = create();
    build(root,1,n);
    int p,x;
    while(m--){
        cin >> opt;
        if(opt == 1){//point edit
            cin >> p >> x;
            u = v = id[p] , w = x;
            edit(root);
        } else if(opt == 2){//tree edit
            cin >> p >> x;
            u = id[p] , v = id[p] + size[p] - 1 , w = x;
            edit(root);
        } else {//query
            cin >> p;
            ll ans = 0;
            while(top[1] != top[p]){
                u = id[ top[p] ] , v = id[p];
                ans += query(root);
                p = fa[ top[p] ];
            }
            u = id[1] , v = id[p];
            cout << ans + query(root) << "\n";
        }
    }
    return 0;
}